# coding:utf8
"""
通用函数库
"""
import random
import re
from twisted.enterprise import adbapi
import time
import MySQLdb
import logging
import datetime

USER_AGENT_LIST = [
"Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.81 Safari/537.36"
]



def div_list_2(ls, n):
	"""
	等分切割列表,
	n : 切割的大小
	"""
	len_ls = len(ls)
	times = len_ls/n 	# 组数
	last_num = len_ls%n # 最后一次

	datas = []
	if times == 0:
		datas.append(ls)
	else:
		num = 0
		for i in range(times):
			datas.append(ls[i*n:(i+1)*n])
		if last_num > 0:
			datas.append(ls[-last_num:])
	return datas
			

def div_list(ls, n):
	'''
	Function doc
	等分切割list
	Parameter doc
	@ls : 列表(list)
	@n : int 切割次数
	return list 返回切割后的list
	'''
	if not isinstance(ls,list) or not isinstance(n,int):  
		return []  
	ls_len = len(ls)  
	if n<=0 or 0==ls_len:  
		return [ls]  
	if n > ls_len:  
		return [ls]  
	elif n == ls_len:  
		return [[i] for i in ls]
	else:  
		j = ls_len/n  
		k = ls_len%n  
		### j,j,j,...(前面有n-1个j),j+k  
		#步长j,次数n-1  
		ls_return = []  
		for i in xrange(0,(n-1)*j,j):  
			ls_return.append(ls[i:i+j])  
		#算上末尾的j+k  
		ls_return.append(ls[(n-1)*j:])  
		return ls_return  


def get_key_and_values_key(item):
	"""
	获取key = VALUES(key)
	"""
	values = ','.join(['%s = VALUES(%s)' % (key, key) for key in item.keys()])
	str_ = 'ON DUPLICATE KEY UPDATE '
	return  str_ + values


def pick_str(str_,  bs,  es='"'):
	"""
	Function doc
	切割字符串, 从bs开始切割, 到es结束
	"""
	bs_len = len(bs)    	# bs 的字符串长度
	a = str_.find(bs)    	# str_ 找到 bs 的位置

	if a != -1:
		if es:
			b = str_.find(es, a+bs_len)  			# 从 str_ 的 bs 之后开始查找 es
			if b != -1: 							# b 是找到es 的位置
				return str_[a+bs_len:b].strip()  	# str切片取 bs之后 到es 之间的字符串
		else:
			return str_[a+bs_len:].strip()

	return ''


def get_diff_time(start,  end):
	"""
	Function doc
	计算两个时间的时间差, 返回的是秒
	@start: 开始时间 如:'2017-04-17 18:00:01'
	@end: 结束时间 如:'2017-04-17 19:00:01'
	"""
	try:
		start = datetime.datetime.strptime(start, "%Y-%m-%d %H:%M:%S")
		end = datetime.datetime.strptime(end, "%Y-%m-%d %H:%M:%S")
		job_time = (start-end).total_seconds()
		return abs(job_time)
	except Exception as e:
		print (e)
		return 0


def select_description(conn, sql):
	"""
	Function doc
	读取数据库表字段名和字段值
	"""
	cur = conn.cursor()		# 创建实例
	item = {}
	try:
		cur.execute(sql)
		data = cur.fetchall()
		description = cur.description 	# 字段描述
		item['data'] = data
		item['description'] = description
	except MySQLdb.Error as e:
		print ('MysqlError %s : %s' % (e[0],  e[1]))
	cur.close()		# 关闭实例

	return item


def exec_sql(conn, sql):
	"""
	执行sql
	:param conn: 
	:param sql: 
	:return: 
	"""
	try:
		cur = conn.cursor()
		cur.execute(sql)
		conn.commit()
		cur.close()
	except MySQLdb.Error as e:
		print ('MysqlError %s : %s' % (e[0],  e[1]))
		return None


def data_types_2_str(datas):
	"""
	mysql查询结果转成字符串类型
	:param datas: mysql查询结果
	:return datas:
	"""
	datas = list(datas)
	for i in range(len(datas)):
		datas[i] = list(datas[i])
		for j in range(len(datas[i])):
			if isinstance(datas[i][j], unicode):
				datas[i][j] = datas[i][j].encode('utf8', 'ignore')
			if isinstance(datas[i][j], datetime.datetime):
				datas[i][j] = datas[i][j].strftime("%Y-%m-%d %H:%M:%S")
			if isinstance(datas[i][j], datetime.date):
				datas[i][j] = datas[i][j].strftime("%Y-%m-%d")
	return datas


def select_data(conn, table, sql):
	"""
	Function doc
	返回数据库查询结果
	Parameter doc
	@conn : Mysql连接实例
	@table : 表名  
	@sql : sql语句 
	return data
	"""
	try:
		cur = conn.cursor()
		cur.execute(sql)
		data = cur.fetchall()
		cur.close()
		print ('table "%s" exec sql success ' % table)
	except MySQLdb.Error as e:
		print ('MysqlError %s :%s %s' % (e[0], table, e[1]))
		return None
	return data


def select_data_new(conn, table, sql):
	"""
	Function doc
	返回数据库查询结果
	Parameter doc
	@conn : Mysql连接实例
	@table : 表名  
	@sql : sql语句 
	return data
	"""
	datas = None
	try:
		cur = conn.cursor()
		cur.execute(sql)
		datas = cur.fetchall()
		cur.close()
		print ('table "%s" exec sql success ' % table)
	except MySQLdb.Error as e:
		print ('MysqlError %s :%s %s' % (e[0], table, e[1]))

	items = []
	if datas:
		for data in datas:
			data = list(data)
			for i in range(len(data)):
				if isinstance(data[i], unicode):
					data[i] = data[i].encode('utf-8')
				else:
					data[i] = str(data[i])
			items.append(data)

	return items


def get_conn(dbs=None, db_type=None, db=None):
	"""
	Function doc
	创建Mysql 数据库连接实例
	Parameter doc
	@dbs 数据库地址库集合
	@db_type 选择数据库类型
	return conn 数据库连接实例
	"""
	conn = None
	if not db:
		if (
			not db_type
			or not isinstance(db_type, str)
			or not isinstance(dbs, dict)
			or db_type not in dbs.keys()):

			return
		db = dbs[db_type]

	try:
		conn = MySQLdb.connect(
			host=db['MYSQL_HOST'],
			user=db['MYSQL_USER'],
			passwd=db['MYSQL_PASSWD'],
			charset='utf8', port=3306)
		conn.select_db(db['MYSQL_DBNAME'])
	except MySQLdb.Error as e:
		print ('MysqlError %s :%s' % (e[0], e[1]))
		print ("conn mysql fail...")

	return conn


def mysql_dbpool_exec(conn, sql):
	"""
	Function doc
	连接池调用方法
	@conn 数据库连接
	@sql 
	"""
	logging.log(logging.INFO,  "---sql len---:" + str(len(sql)))
	try:
		conn.execute(sql)
		print ('exec successful')
	except MySQLdb.Error as e:
		logging.log(logging.INFO,  "MySQL error:" + str(e))


def insert_ignore_dicts_sql(dicts, table, types=None):
	"""
	Function doc
	将一组 dict 转换成sql
	Parameter doc
	@dicts : 一个list包含多个dict 如: [{'a':1}, {'a':2}]
	@table : 表名
	"""
	vals = []
	sql = ''

	try:
		for i in range(len(dicts)):
			sql = get_i2_sql(table, dicts[i])		# 生成sql
			val = dict_2_value(dicts[i])			# 生成结果
			vals.append(val)
		sql += ','.join(vals)
		if types:
			sql += types
	except Exception as e:
		print (e)
	return sql


def dict_2_value(dict_):
	"""
	Function doc
	python dict 
	默认是根据key值 排序的,  只要key值一致 
	那么结果排序也是一致的
	将字典变成，('value', 'value') 的形式
	Parameter doc
	@dict : 字典
	return ('value', 'value')
	"""
	tmplist = []
	for k,  v in dict_.items():
		if isinstance(v, unicode):
			v = v.encode('utf-8', "ignore")
		try:
			tmp = "%s" % safe(str(v))
		except Exception as e:
			logging.log(logging.INFO, e)
			return
		tmp = "'"+tmp+"'"
		tmplist.append(tmp)
	val = '('+', '.join(tmplist)+')'
	return val


def safe(s):
	"""
	对字段不转义
	:param s: 
	:return: 
	"""
	return MySQLdb.escape_string(s) 	# 对字段不转义


def get_i2_sql(table, dict_):
	"""
	Function doc
	生成sql 类似 : INSERT INTO table (key, key, key)  VALUES
	Parameter doc
	@table : 表名
	@dict : 字典数据
	return sql
	"""
	field = dict_2_field(dict_) 		# 返回字段(key, key, key)
	sql = 'INSERT IGNORE INTO %s %s  VALUES ' % (table, field)
	return sql


def dict_2_field(dict_):
	"""
	Function doc
	将字典变成，('key', 'key')
	Parameter doc
	@dict_ : 字典
	return ('key', 'key')
	"""
	field_list = []
	for k,  v in dict_.items():
		fields = "`%s`" % str(k)
		field_list.append(fields)

	field = '('+', '.join(field_list)+')'
	return field


def get_dbpool(dbs=None,  db_type=None,  db=None):
	"""
	Function doc
	创建Mysql 数据库连接池实例
	Parameter doc
	@dbs 数据库地址库集合
	@db_type 选择数据库类型
	return dbpool 数据库连接池实例
	"""
	dbpool = None
	if not db:
		if (
			not db_type
			or not isinstance(db_type, str)
			or not isinstance(dbs, dict)
			or db_type not in dbs.keys()):
			return
		db = dbs[db_type]

	try:
		dbargs = dict(
			host=db['MYSQL_HOST'],
			db=db['MYSQL_DBNAME'],
			user=db['MYSQL_USER'],
			passwd=db['MYSQL_PASSWD'],
			port=3306,
			charset='utf8',
			# cursorclass = MySQLdb.cursors.DictCursor,
			# use_unicode= True,
		)
		dbpool = adbapi.ConnectionPool('MySQLdb',  **dbargs)
	except Exception as e:
		print (e)

	return dbpool


def unicode_2_utf8(item):
	"""
	Function doc
	将unicode编码字段, 转成utf8编码
	Parameter doc
	@item : 字典(dict)
	return dict 返回utf8编码的字典
	"""
	for key in item.keys():
		if isinstance(item[key],  unicode):
			item[key] = item[key].encode('utf-8',  "ignore")
	return item


def unicode_2_utf8_new(s):
	"""
	Function doc
	将unicode编码字段, 转成utf8编码
	Parameter doc
	@s : 字符串
	return s
	"""
	if isinstance(s,  unicode):
		s = s.encode('utf-8',  "ignore")
	return s



def ua_request(request, headers=''):
	"""
	Function doc
	更改 request 实例 的请求头 主要是加 User-Agent
	Parameter doc
	@request : url请求实例
	@headers : dict  请求头
	return request 请求实例
	"""
	if headers and isinstance(headers,  dict):
		for k, v in headers.items():
			request.headers[k] = v
		if 'User-Agent' not in headers.keys() and 'user-agent' not in headers.keys():
			request.headers['User-Agent'] = random.choice(USER_AGENT_LIST)
	else:
		request.headers['User-Agent'] = random.choice(USER_AGENT_LIST)
	return request


def fmt_text(str_, level=2):
	"""
	Function doc
	替换str中的特殊字符
	return str
	"""
	if not str_:
		return ''

	str_ = str_.strip().replace(', ', '%2C').replace('\n', ' ')
	if level == 2:
		str_ = re.sub(r'/$', '', re.sub(r'&#\d+;?', '', str_.replace('&amp;', '&').replace('&amp;', '&')).strip())
	return str_


def exec_cmd(cmd):
	"""
	执行cmd
	:param cmd: 
	:return: 
	"""
	print ("[cmd]: %s" % cmd)
	import subprocess
	p = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE)
	out = p.wait()
	print ("[out]: %s" % out)


"""
End funcs.py
"""